#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    :   MyLael
@Time    :   2023/2/22 19:12:19
@author  :   Eval
@Version :   1.0
@Describe:   重写 Qlabel, 实现鼠标点击事件
'''

from PySide6.QtCore import (QRect,Qt,QSize)
from PySide6.QtWidgets import (QLabel,QScrollArea,QPushButton)
from PySide6.QtGui import (QPixmap,QMouseEvent,QEnterEvent,QKeyEvent)
from editRun import MyWidget 
from conf.GameLogin import *
from map.mapManage.mapMgr import *

class MyLabel(QLabel):
    """重写标签,可触发点击事件"""
    def __init__(self,form,x,y,w,h,name="未命名的标签",pix=None,pixCopy=None,offset=0,tag=None):
        super().__init__(form)
        self.form:MyWidget = form
        self.offset:int = offset
        self.setGeometry(QRect(x,y,w,h))
        self.setObjectName(name)
        self.pix:QPixmap = pix
        self.pixCopy:QPixmap = pixCopy
        self.data:dict = None
        self.parent:QScrollArea = None

        self.tag = tag
        self.animIndex:int = 0
        self.animMax:int = None

        # 如果是选中框的话, 那么使用一个原型变量存储被挡住的元素吧
        self.ProtoType = None
        if pix is None:
            self.setText(name)
        else:
            self.setPixmap(self.pix)
    
    def mousePressEvent(self, ev: QMouseEvent) -> None:
        """鼠标点击事件,按下按钮即刻生效"""
        self.form.MousePress = True
        return super().mousePressEvent(ev)
            
    def mouseReleaseEvent(self, e: QMouseEvent) -> None:
        """鼠标点击事件,抬起按钮之后才会生效"""
        # 鼠标抬起时,状态重置
        self.form.MousePress = False
        if len(self.form.LastAddPointDict):
            if self.form.MouseCurrowItem and self.form.SourceCache.get(f"{self.form.MouseCurrowItem['type']}-{self.form.MouseCurrowItem['index']}"):
                # 根据选中框的原型对象将当前鼠标悬浮的对象 指向为真实的素材,  实现点击穿透
                if not self.ProtoType is None:
                    self = self.ProtoType
                data =  self.form.SourceCache.get(f"{self.form.MouseCurrowItem['type']}-{self.form.MouseCurrowItem['index']}")
                MapKey =  data["key"]
                render_num = 0
                for pos in self.form.LastAddPointDict:
                    pos = pos.split(",")
                    if self.form.map[int(pos[0])][int(pos[1])] == int(MapKey):
                        # 相同素材,跳过
                        continue
                    render_num += 1
                    # 将对应的 key写入地图, 而不是将当前素材的索引序列号写入地图
                    self.updateLab(int(pos[0]),int(pos[1]),QPixmap(f'lib/images/{self.form.MouseCurrowItem["type"]}.png'),
                                    self.form.MouseCurrowItem["index"]*32,self.form.MouseCurrowItem["rect"][0],self.form.MouseCurrowItem["rect"][1],
                                    int(data["key"]),data,int(data["animMax"]))
                self.form.updateMap() # 手动执行刷新地图, 解决没法生成后地图没有立刻重新渲染的问题
                self.form.addLog(f"连续渲染了:{render_num} 个图块")
            self.form.LastAddPointDict.clear()
            return
        # 如果触发了双击之后才进来的单击事件,那么将状态重置并本次不执行
        if self.form.MouseDouble:
            self.form.MouseDouble = False
            return
        if e.button() == Qt.MouseButton.LeftButton:
            # 根据选中框的原型对象将当前鼠标悬浮的对象 指向为真实的素材,  实现点击穿透
            if not self.ProtoType is None:
                self = self.ProtoType
            # 隐藏菜单
            self.form.MMenus.hide()
            if self.tag == "map":
                pos = self.objectName().split(",")
                # 如果当前选中的有素材 且 这个素材已经注册了
                if self.form.MouseCurrowItem and self.form.SourceCache.get(f"{self.form.MouseCurrowItem['type']}-{self.form.MouseCurrowItem['index']}"):
                    data =  self.form.SourceCache.get(f"{self.form.MouseCurrowItem['type']}-{self.form.MouseCurrowItem['index']}")
                    MapKey =  data["key"]
                    if self.form.map[int(pos[0])][int(pos[1])] == int(MapKey):
                        # print("相同素材,设为地板")
                        self.updateLab(int(pos[0]),int(pos[1]))
                        return
                    if data is None:
                        self.form.addLog(f"未知元素:{MapKey}!")
                        return
                    # 将对应的 key写入地图, 而不是将当前素材的索引序列号写入地图
                    self.updateLab(int(pos[0]),int(pos[1]),QPixmap(f'lib/images/{self.form.MouseCurrowItem["type"]}.png'),
                                   self.form.MouseCurrowItem["index"]*32,self.form.MouseCurrowItem["rect"][0],self.form.MouseCurrowItem["rect"][1],
                                   int(MapKey),data,int(data["animMax"]))
                    return
                    

                # 当空闲状态下点击地图事件
                if not self.form.mapEvn.get(self.objectName()) is None:
                    self.form.addLog(f"{self.objectName()}:有事件")
                    return
                if self.data is None:
                    if self.form.ui.ShowDiaLog_Window("该坐标的元素注册数据已丢失,是否清除该点?") == DiaLogResult.OK:
                        self.updateLab(pos[0],pos[1])
                    else:
                        self.form.addLog(f"未知事件点 坐标:{self.objectName()}")
                        
                    return
                self.form.addLog(f"类型:{self.data['type']}  索引:{self.data['index']}  ID:{self.data['key']} 坐标:{self.objectName()}")


            if type(self.parent) != QScrollArea:
                # 以下逻辑仅对素材区域的滚动条生效
                return
            
            MType = self.objectName()
            MIndex = int(e.position().y()) //32
            self.form.MouseCurrowItem ={
                "type": MType,
                "index": MIndex,
                "rect": [32, 32],
                "animIndex": 0,
                "animMax": 0
            }
            
            if self.form.SourceCache.get(f"{MType}-{MIndex}"):
                self.form.addLog(f"元素:{MType}-{MIndex}已经注册,可以直接使用",level=1)
                self.form.selectPreView.setEnabled(True)
                # 将当前注册的id填充到标签
                MapKey =  self.form.SourceCache.get(f"{MType}-{MIndex}")["key"]
            else:
                self.form.addLog(f"元素:{MType}-{MIndex} 没有注册,请先注册后在使用",level=3)
                self.form.selectPreView.setEnabled(False)
                
            # 屏幕下方居中的位置 显示当前选中素材的预览
            pix = self.pix.copy(0,MIndex*32,32,32)
            pix = pix.scaled(QSize(self.form.selectPreView.width(),self.form.selectPreView.height()))
            self.form.selectPreView.setPixmap(pix)
            
        elif e.button() == Qt.MouseButton.RightButton:
            if not self.ProtoType is None:
                self = self.ProtoType
            if self.tag == "map":
                pos = self.objectName().split(",")
                # 取消选中素材的状态
                self.form.resertPreView()
                # 显示菜单
                self.form.MMenus.show(pos=pos,lab=self)
                # 选中框
                self.form.item_selected.setVisible(True)
                self.form.item_selected.move(int(pos[1])*32,int(pos[0])*32)
                self.form.item_selected.ProtoType = self
                
            elif self.tag == "source":
                MIndex = int(e.position().y()) //32
                self.form.editSource.showUI(self,MIndex)
                

        return super().mouseReleaseEvent(e)
    
    def mouseMoveEvent(self, ev: QMouseEvent) -> None:
        # 根据选中框的原型对象将当前鼠标悬浮的对象 指向为真实的素材,  实现点击穿透
        if not self.ProtoType is None:
            self = self.ProtoType
        # 取整个屏幕的鼠标坐标, 判断点击区域是否超过了地图大小
        mouseX = int(ev.scenePosition().y()) //32
        mouseY = int(ev.scenePosition().x()) //32
        if mouseX > 13 or mouseY > 13:
            return
        # 只记录没有存在路径点中的坐标
        if not f"{mouseX},{mouseY}" in self.form.LastAddPointDict:
            self.form.LastAddPointDict.append(f"{mouseX},{mouseY}")
        # self.form.MousePress = True
        return super().mouseMoveEvent(ev)

    def enterEvent(self, e: QEnterEvent) -> None:
        # 如果是按下按钮的状态, 那么跳出
        if self.form.MousePress:
            return
        if self.tag == "map":
            # 如果菜单是显示的状态, 那么选中框不跟随
            if self.form.MMenus.menuWin.isVisible():
                return
            pos = self.objectName().split(",")
            self.form.item_selected.setVisible(True)
            self.form.item_selected.move(int(pos[1])*32,int(pos[0])*32)
            self.form.item_selected.ProtoType = self
        return super().enterEvent(e)

    def mouseDoubleClickEvent(self, e: QMouseEvent) -> None:
        """鼠标双击元素"""
        # 不是左键则跳出
        if e.button() != Qt.MouseButton.LeftButton:
            return
        # 根据选中框的原型对象将当前鼠标悬浮的对象 指向为真实的素材,  实现点击穿透
        if not self.ProtoType is None:
            self = self.ProtoType
        # 隐藏菜单
        self.form.MMenus.hide()
        if self.tag == "map":
            MType = self.data["type"]
            MIndex = self.data["index"]
            
            self.form.MouseCurrowItem ={
                "type": MType,
                "index": MIndex,
                "rect": [32, 32],
                "animIndex": 0,
                "animMax": 0
            }
            self.form.addLog(f"元素:{MType}-{MIndex}已经注册,可以直接使用",level=1)
            self.form.selectPreView.setEnabled(True)
                
            # 屏幕下方居中的位置 显示当前选中素材的预览
            pix = self.pix.scaled(QSize(self.form.selectPreView.width(),self.form.selectPreView.height()))
            self.form.selectPreView.setPixmap(pix)
            # 双击状态
            self.form.MouseDouble = True
        return super().mouseDoubleClickEvent(e)
    
    def playLabAnim(self):
        """执行动画"""
        # 如果当前元素的data是None, 那么跳出
        if self.data is None:
            return
        # 如果动画帧是0 或者 触发器是 openDooor 的图块不执行动画
        if not int(self.animMax) or (not self.data.get("trigger") is None and self.data.get("trigger") == "openDoor"):
            return
        pix = self.form.GC.GameSurfaceCache.get(f'{self.objectName()}-{self.animIndex}-{self.data["index"]}')
        # 写入缓存
        if pix is None:
            pix = self.pixCopy.copy(self.animIndex*32,self.data["index"]*32,32,32)
            self.form.GC.GameSurfaceCache[f'{self.objectName()}-{self.animIndex}-{self.data["index"]}'] = pix
        self.setPixmap(pix)
        self.animIndex = (self.animIndex +1) % int(self.animMax)

    def updateLab(self,MapX,MapY,pix = None,pixY=0,pixW=32,pixH=32,MapKey=0,data=None,animMax=0):
        """更新地图点元素"""
        # 将缓存清空
        self.form.GC.GameSurfaceCache.clear()
        if data is None:
            data = self.form.SourceMgr[list(self.form.SourceMgr.keys())[0]]
            pix = QPixmap(f'lib/images/{data["type"]}.png')
        MapX,MapY = int(MapX),int(MapY)
        self.form.map[MapX][MapY] = MapKey
        self.data = data  # 必须要重置data, 不然在执行渲染动画的时候, 还是会显示之前的素材
        self.pixCopy = pix  # 备份的图像必须是完整的原始图像,(没有被copy部分区域的备份)
        self.pix = pix.copy(0,pixY,pixW,pixH)
        self.animIndex = 0
        self.animMax = animMax
        self.setPixmap(self.pix)
        self.form.IsSaveMap = False

    def __str__(self) -> str:
        return self.objectName()